<?php
/**
 * Created by PhpStorm.
 * User: tangping
 * Date: 16/4/20
 * Time: 下午3:04
 */
namespace Server;
//use \Library\StateCode;
define('APP_PATH', realpath('..'));

class Server
{
    private static $instance;
    private static $server;
    private static $swoole_table;
    private $di;
    private $worker_id = [];

    private function __construct()
    {
        $table = new \swoole_table(8192);
        $table->column('data', \swoole_table::TYPE_STRING, 20000);
        $table->create();
        self::$swoole_table=$table;
        $server = new \swoole_websocket_server('0.0.0.0', 9502);
        self::$server=$server;
        $server->set(array(
            'worker_num' => 50,
            'daemonize' => false,
            'max_request' => 100000,
            'dispatch_mode' => 1,
            'task_worker_num' => 8
        ));
        $server->on('WorkerStart', array($this, 'onWorkerStart'));
        $server->on('request', array($this, 'onRequest'));
        $server->on('WorkerStop', array($this, 'onWorkerStop'));
        $server->on('Task', array($this, 'onTask'));
        $server->on('Finish', array($this, 'onFinish'));
        $server->on('Message',array($this,'onMessage'));
        $server->setGlobal(HTTP_GLOBAL_ALL);
        $server->start();

    }

    public function onWorkerStart($serv, $worker_id)
    {
        $config = include_once APP_PATH . "/config/config.php";
        require_once APP_PATH . "/config/routes.php";
        require_once APP_PATH . "/config/services.php";
        require_once APP_PATH . "/config/loader.php";
        $this->di = $di;
        $this->worker_id[$worker_id] = $serv->worker_pid;
        if ($worker_id === 0) {
            $serv->tick(10000, function ($id) use ($serv) {
                $this->onTimer($serv, $id);
            });
        }
    }

    public function onMessage(){}

    public function onRequest($request, $response)
    {
        ob_start();
        try {
            $_GET['_url'] = $request->server['request_uri'];
            $application = new \Phalcon\Mvc\Application($this->di);
            $GLOBALS['application']=$application;
            $this->include_module($application);

            defined('PUBLICDIR') || define('PUBLICDIR',$this->di->get('url')->getBaseUri());
            defined('TIMESTAMP') || define('TIMESTAMP',time());
            defined('SHELL') || define('SHELL','php');
            echo $application->handle()->getContent();
        } catch (\Exception $e) {
            echo $e->getMessage();
        }
        $result = ob_get_contents();
        ob_end_clean();
        $response->end($result);
    }

    public function onTimer($serv, $interval)
    {
//        $serv->task('check_run_file');
    }

    public function onTask($serv, $task_id, $from_id, $data)
    {
        $type=is_array($data)?$data['type']:$data;
        switch($type){
            case 'check_run_file':

                break;
            case 'modelEvent':
                $name='\Events\\'.$data['model'];
                $state=$name::$data['event']($data);
                $serv->finish(array('data'=>$data,'state'=>$state));
                break;
        }
    }

    public function onFinish($serv,$task_id,$data)
    {
        if(is_array($data)){
            if(!$data['state']){
                $serv->task($data['data']);
            }
        }

    }

    public function onWorkerStop($serv, $worker_id)
    {
        unset($this->worker_id[$worker_id]);
    }

    private function include_module($app){
        $app->registerModules(array(

            'admin' => array(
                'className' => 'Admin\Module',
                'path' => __DIR__ . '/../apps/admin/Module.php'
            ),
            'frontend' => array(
                'className' => 'Frontend\Module',
                'path' => __DIR__ . '/../apps/frontend/Module.php'
            )
        ));
    }

    public static function getInstance()
    {
        if (!self::$instance instanceof self) {
            self::$instance = new self;
        }
        return self::$instance;
    }

    public static function getServer(){
        return self::$server;
    }

    public static function getTable(){

        return self::$swoole_table;
    }
}

Server::getInstance();